/*
 * Types, Variables and Arithmetic
 *
 */

#include <complex>
#include <iostream>

using namespace std;

constexpr double average_square(double x, double y) {
    return x * x + y * y / 2;
}

int main() {
    // try the c++11 feature, "Initializer Lists", using the
    // curly-brace-delimited
    // `{...}`.
    auto i1{7.8};
    auto i2{complex<double>(1.2, 3.5)};
    auto q{sqrt(2.0)};
    auto bb{true};
    cout << i1 << endl;
    cout << i2 << endl;
    cout << q << endl;
    cout << bb << endl;

    // const vs constexpr
    // `const` is used primarily to specify interfaces, to transfer
    // pointers/references without fear of it being modified. `constexpr` must
    // be calculated by the compiler, with some simple operator,
    //   such as the arithmetic(+-*/%) or the bool operation or the bitwise
    //   operation.
    const auto sq = sqrt(i1);
    // constexpr auto csq = sqrt(7.8);  // Compile Error, because of `sqrt`
    constexpr auto csq = 8 % 3;
    cout << sq << endl;
    cout << csq << endl;

    // `Constexpr` Function
    cout << average_square(3.3, 2) << endl;
    // Special Case: Constexpr Function can be used for non-constant arguments.
    //   That way, the program don’t have to define essentially the same
    //   function twice: once for constant expressions and once for variables.
    double x, y;
    cin >> x >> y;
    cout << average_square(x, y) << endl;
    return 0;
}
